1 module unde.games.dizzy.omega.bug; 2 3 import derelict.opengl3.gl; 4 5 import std.conv; 6 import std.math; 7 import unde.games.object; 8 import unde.games.renderer; 9 import unde.games.collision_detector; 10 import unde.games.object; 11 import unde.games.dizzy.omega.main; 12 import unde.global_state; 13 14 class Bug:StaticGameObject 15 { 16 static int num; 17 int number; 18 19 bool killed; 20 bool sprayed; 21 22 enum SPEED = 0.05; 23 enum G = 0.0025; 24 enum MAX_V = 0.05; 25 enum JUMP_V = 0.075; 26 27 float def_x, def_y, def_z; 28 float dx = SPEED, dy = 0.0; 29 long frame; 30 31 bool search_surface; 32 bool jump_mode; 33 34 this(MainGameObject root, float[3] coords, string bug_solid, bool jump_mode = false) 35 { 36 def_x = x = coords[0]; 37 def_y = y = coords[1]; 38 def_z = z = coords[2]; 39 number = num++; 40 models["bug"] = root.models["bug"]; 41 collision_objects["solid"] = root.collision_objects[bug_solid]; 42 this.jump_mode = jump_mode; 43 super(root); 44 } 45 46 bool walk_anim(GlobalState gs, string name) 47 { 48 float f = (frame*4)%120; 49 float f2 = (frame*4)%240; 50 float degree = 0.0; 51 float translate = 0.0; 52 53 if (f < 60.0) 54 translate = -0.1 + 0.2*f/60.0; 55 else if (f < 120.0) 56 translate = 0.1 - 0.2*(f - 60.0)/60.0; 57 58 if (f2 < 120.0) 59 degree = f2/2 - 30.0; 60 else if (f2 < 240.0) 61 degree = 30.0 - (f2/2 - 60.0); 62 63 if (name == "Bug-FL_Leg") 64 { 65 glTranslatef(0.5, 0.4, 0.0); 66 glRotatef(degree, 0.0, 0.0, 1.0); 67 glTranslatef(-0.5, -0.4, 0.0); 68 } 69 70 if (name == "Bug-FR_Leg") 71 { 72 glTranslatef(0.5, 0.4, 0.0); 73 glRotatef(-degree, 0.0, 0.0, 1.0); 74 glTranslatef(-0.5, -0.4, 0.0); 75 } 76 77 if (name == "Bug-BL_Leg") 78 { 79 glTranslatef(-0.5, 0.4, 0.0); 80 glRotatef(-degree, 0.0, 0.0, 1.0); 81 glTranslatef(0.5, -0.4, 0.0); 82 } 83 84 if (name == "Bug-BR_Leg") 85 { 86 glTranslatef(-0.5, 0.4, 0.0); 87 glRotatef(degree, 0.0, 0.0, 1.0); 88 glTranslatef(0.5, -0.4, 0.0); 89 } 90 91 if (name == "Bug-Head") 92 { 93 glTranslatef(0.8, 0.4, 0.0); 94 glRotatef(degree/2, 0.0, 1.0, 0.0); 95 glTranslatef(-0.8, -0.4, 0.0); 96 } 97 98 return true; 99 } 100 101 void kill() 102 { 103 killed = true; 104 } 105 106 void spray() 107 { 108 sprayed = true; 109 } 110 111 override void draw(GlobalState gs) 112 { 113 if (killed) return; 114 115 glPushMatrix(); 116 glTranslatef(x, y, z); 117 if (dx < 0) glRotatef(180,0,1,0); 118 recursive_render(gs, models["bug"], &walk_anim); 119 glPopMatrix(); 120 } 121 122 immutable float side_sensor_dx = 1.0; 123 immutable float[2] side_sensor_y = [0.5, 0.8]; 124 125 immutable float bottom_sensor_dx = 0.6; 126 immutable float bottom_sensor_dy = 0.5; 127 128 override bool tick(GlobalState gs) 129 { 130 if (killed) return true; 131 132 frame++; 133 x += dx; 134 y += dy; 135 136 if (!jump_mode) 137 { 138 if (dx < 0 && (if_intersect (collision_objects["solid"], [x-side_sensor_dx, y+side_sensor_y[0], z-5*side_sensor_dx, x, y+side_sensor_y[1], z+5*side_sensor_dx]) > 0)) 139 { 140 dx = SPEED; 141 } 142 143 if (dx > 0 && (if_intersect (collision_objects["solid"], [x, y+side_sensor_y[0], z-side_sensor_dx, x+5*side_sensor_dx, y+side_sensor_y[1], z+5*side_sensor_dx]) > 0)) 144 { 145 dx = -SPEED; 146 } 147 } 148 149 Intersect on_the_ground = 150 if_intersect (collision_objects["solid"], [x-bottom_sensor_dx, y, z-5*bottom_sensor_dx, x+bottom_sensor_dx, y+bottom_sensor_dy, z+5*bottom_sensor_dx]); 151 152 if (jump_mode) 153 { 154 if (on_the_ground && (if_intersect (collision_objects["solid"], [x, y+side_sensor_y[0], z-5*side_sensor_dx, x+2*side_sensor_dx, y+side_sensor_y[1], z+5*side_sensor_dx]) > 0) || 155 abs(x - 475.6) < 0.25) 156 { 157 dx = SPEED/2; 158 dy = JUMP_V; 159 search_surface = false; 160 } 161 } 162 163 if (dy > -MAX_V) 164 { 165 dy -= G; 166 } 167 168 if (search_surface && on_the_ground == 0) 169 { 170 if (jump_mode) dx = SPEED; 171 dy = 0; 172 search_surface = false; 173 } 174 175 if (on_the_ground > 0 && (dy <= 0 || search_surface)) 176 { 177 if (if_intersect (collision_objects["solid"], [x-bottom_sensor_dx, y+SPEED, z-5*bottom_sensor_dx, x+bottom_sensor_dx, y+SPEED+bottom_sensor_dy, z+5*bottom_sensor_dx]) > 0) 178 { 179 search_surface = true; 180 dy = SPEED; 181 } 182 else if (on_the_ground > 0) dy = 0; 183 } 184 185 DizzyOmega dz = cast(DizzyOmega) root; 186 187 if (!dz.stone1.inventory && abs(dz.stone1.x - 242.6) < 0.1 && abs(dz.stone1.y + 4.4) < 0.1 || 188 !dz.stone2.inventory && abs(dz.stone2.x - 242.6) < 0.1 && abs(dz.stone2.y + 4.4) < 0.1) 189 { 190 if (abs(x - 242.6) > 1.5 && abs((x+dx) - 242.6) < 1.5) 191 { 192 dx = -dx; 193 } 194 } 195 else if (!dz.stone1.inventory && abs(dz.stone1.x - 242.6) < 0.1 && abs(dz.stone1.y + 5.2) < 0.1 || 196 !dz.stone2.inventory && abs(dz.stone2.x - 242.6) < 0.1 && abs(dz.stone2.y + 5.2) < 0.1) 197 { 198 if ( abs(x - 242.6) > 1.5 && abs((x+dx) - 242.6) < 1.5 ) 199 { 200 dy = JUMP_V; 201 search_surface = false; 202 } 203 } 204 205 return true; 206 } 207 208 override void load(string[string] s) 209 { 210 string p = "bug"~number.to!(string); 211 if (p~"-x" in s) 212 x = s[p~"-x"].to!(float); 213 else 214 x = def_x; 215 216 if (p~"-y" in s) 217 y = s[p~"-y"].to!(float); 218 else 219 y = def_y; 220 221 if (p~"-z" in s) 222 z = s[p~"-z"].to!(float); 223 else 224 z = def_z; 225 226 if (p~"-dx" in s) 227 dx = s[p~"-dx"].to!(float); 228 else 229 dx = SPEED; 230 231 if (p~"-dy" in s) 232 dy = s[p~"-dy"].to!(float); 233 else 234 dy = 0.0; 235 236 if (p in s) 237 { 238 killed = (s[p] == "killed"); 239 } 240 else 241 killed = false; 242 243 if (p~"-s" in s) 244 { 245 sprayed = (s[p~"-s"] == "sprayed"); 246 } 247 else 248 sprayed = false; 249 } 250 251 override void save(ref string[string] s) 252 { 253 string p = "bug"~number.to!(string); 254 if (killed) 255 s[p] = "killed"; 256 257 if (sprayed) 258 s[p~"-s"] = "sprayed"; 259 260 s[p~"-x"] = x.to!(string); 261 s[p~"-y"] = y.to!(string); 262 s[p~"-z"] = z.to!(string); 263 s[p~"-dx"] = dx.to!(string); 264 s[p~"-dy"] = dy.to!(string); 265 } 266 }